﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading;
using log4net;
using PriceLibrary.ChartService;

namespace PriceLibrary.Utilities
{
    [Obsolete("Don't use anymore.")]
    public class ChartCallbackManager : DuplexServiceManager, IDisposable
    {
        private readonly ILog _log = LogManager.GetLogger(typeof(ChartCallbackManager));

        #region Contructors
        public ChartCallbackManager(string chartUri)
        {
            ServiceUri = chartUri;
            Init(chartUri);
        }
        #endregion Contructors

        public DuplexChannelFactory<IChartService> ChannelFactory { get; set; }

        [Obsolete("Not used anymore.")]
        public IChartService CreateChartChannel(ChartCallBack chartCallBack)
        {
            if (chartCallBack == null) throw new ArgumentNullException("ChartCallBack Must not be null!");
            ChartCallBack callBack = chartCallBack;
            IChartService chartService = ChannelFactory.CreateChannel(new InstanceContext(callBack));

            //try
            //{
            //    //((ICommunicationObject)chartService).Faulted += delegate(object seander, EventArgs e)
            //    //{
            //    //    ResolveFaultState(chartService,callBack);

            //    //};
            //    //if (((ICommunicationObject)chartService).State != CommunicationState.Opened) 
            //    ((ICommunicationObject)chartService).Open();

            //}
            //catch (Exception ex)
            //{
            //    _log.Error("Unknown exception when creates channel!", ex);
            //}
            //finally
            //{
            //    callBack.ChartService = chartService;
            //}
            return chartService;
        }

        [Obsolete("Not used anymore.")]
        public ChartCallBack CreateChartCallbackWithServiceChannel()
        {
            ChartCallBack callBack = new ChartCallBack(ServiceUri);
            return callBack;
        }

        private void ResolveFaultState(IChartService chartService, ChartCallBack callBack)
        {
            ICommunicationObject obj = chartService as ICommunicationObject;
            while (obj != null && (((ICommunicationObject)chartService).State == CommunicationState.Faulted || ((ICommunicationObject)chartService).State == CommunicationState.Closed))
            {
                Thread.Sleep(10 * 1000); //10s
                try
                {
                    if (ChannelFactory != null)
                    {
                        if (ChannelFactory.State != CommunicationState.Faulted)
                        {
                            chartService = ChannelFactory.CreateChannel(new InstanceContext(callBack));
                            obj = (ICommunicationObject)chartService;
                            Debug.Print("Begin Open! Chart Callback");
                            obj.Open();
                            //Nếu vượt qua câu lệnh trên -> đã mở connection!
                            //callBack.TransactionsKeeped.Clear();
                            chartService.SubscribeSymbolsWithoutHistory((List<string>)callBack.Symbols);
                            break;
                        }
                    }
                    else
                    {
                        Init(ServiceUri);
                    }
                }
                catch (CommunicationException exception)
                {
                    _log.Error("Server not found! ChartCallback", exception);
                    Debug.Print("Please wait ....ChartCallback");
                }
                catch (Exception ex)
                {
                    _log.Error("Unknow exception! ChartCallback", ex);
                    break;
                }
            }
            ((ICommunicationObject)chartService).Faulted += delegate
            {
                ResolveFaultState(chartService, callBack);
            };

        }

        protected void Init(string uri)
        {
            NetTcpBinding netTcpBinding = new NetTcpBinding(SecurityMode.None);
            netTcpBinding.MaxReceivedMessageSize = netTcpBinding.MaxBufferSize = int.MaxValue;
            netTcpBinding.MaxConnections = 30;

            netTcpBinding.OpenTimeout = TimeSpan.FromMinutes(1.0d);
            netTcpBinding.CloseTimeout = TimeSpan.FromMinutes(1.0d);
            netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;

            EndpointAddress endpointAddress = new EndpointAddress(uri);
            ChannelFactory = new DuplexChannelFactory<IChartService>(typeof(PriceCallBack), netTcpBinding, endpointAddress);

            ChannelFactory.Faulted += FactoryReconnect;

            ChannelFactory.Open();
        }

        public void Reconnect()
        {
            Init(ServiceUri);
        }

        #region Channel Factory & Client Event

        private void FactoryReconnect(object sender, EventArgs e)
        {
            while (ChannelFactory == null || ChannelFactory.State == CommunicationState.Faulted)
            {
                Thread.Sleep(10 * 1000); //10s
                Init(ServiceUri);
            }
        }

        #endregion Channel Factory & client Event

        #region Implementation of IDisposable

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            if (ChannelFactory != null)
            {
                ChannelFactory.Close();
            }
            ChannelFactory = null;

        }

        #endregion
    }
}
